/*!
	@file
	@author		George Evmenov
	@date		07/2009
*/

#include "MyGUI_EggTexture.h"
#include "MyGUI_EggRenderManager.h"
#include "MyGUI_EggDiagnostic.h"
#include "MyGUI_EggPlatform.h"
#include "MyGUI_EggRTTexture.h"

namespace MyGUI
{

	EggTexture::EggTexture(const std::string& _name) :
		mName(_name),
		mLock(false),
		mDataSize(0),
		mUsage(0),
		mBuffer(0),
        mAccess(0),
        mNumElemBytes(0),
		mRenderTarget(nullptr)
	{
	}

	EggTexture::~EggTexture()
	{
		destroy();
	}

	const std::string& EggTexture::getName() const
	{
		return mName;
	}

	void EggTexture::setUsage(TextureUsage _usage)
	{
		mAccess = 0;
		mUsage = 0;

		if (_usage == TextureUsage::Default)
		{
			mUsage = GL_STATIC_READ;
			mAccess = GL_READ_ONLY;
		}
		else if (_usage.isValue(TextureUsage::Static))
		{
			if (_usage.isValue(TextureUsage::Read))
			{
				if (_usage.isValue(TextureUsage::Write))
				{
					mUsage = GL_STATIC_COPY;
					mAccess = GL_READ_WRITE;
				}
				else
				{
					mUsage = GL_STATIC_READ;
					mAccess = GL_READ_ONLY;
				}
			}
			else if (_usage.isValue(TextureUsage::Write))
			{
				mUsage = GL_STATIC_DRAW;
				mAccess = GL_WRITE_ONLY;
			}
		}
		else if (_usage.isValue(TextureUsage::Dynamic))
		{
			if (_usage.isValue(TextureUsage::Read))
			{
				if (_usage.isValue(TextureUsage::Write))
				{
					mUsage = GL_DYNAMIC_COPY;
					mAccess = GL_READ_WRITE;
				}
				else
				{
					mUsage = GL_DYNAMIC_READ;
					mAccess = GL_READ_ONLY;
				}
			}
			else if (_usage.isValue(TextureUsage::Write))
			{
				mUsage = GL_DYNAMIC_DRAW;
				mAccess = GL_WRITE_ONLY;
			}
		}
		else if (_usage.isValue(TextureUsage::Stream))
		{
			if (_usage.isValue(TextureUsage::Read))
			{
				if (_usage.isValue(TextureUsage::Write))
				{
					mUsage = GL_STREAM_COPY;
					mAccess = GL_READ_WRITE;
				}
				else
				{
					mUsage = GL_STREAM_READ;
					mAccess = GL_READ_ONLY;
				}
			}
			else if (_usage.isValue(TextureUsage::Write))
			{
				mUsage = GL_STREAM_DRAW;
				mAccess = GL_WRITE_ONLY;
			}
		}
	}

	void EggTexture::createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format)
	{
		createManual(_width, _height, _usage, _format, 0);
	}

	void EggTexture::createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format, void* _data){
        egg::PixelFormat eggPF;
		if (_format == PixelFormat::L8){
            eggPF=egg::PF_L8;
            mNumElemBytes = 1;
		}else if (_format == PixelFormat::L8A8){
            eggPF=egg::PF_L8A8;
			mNumElemBytes = 2;
		}else if (_format == PixelFormat::R8G8B8){
            eggPF=egg::PF_R8G8B8;
			mNumElemBytes = 3;
		}else if (_format == PixelFormat::R8G8B8A8){
            eggPF=egg::PF_R8G8B8A8;
            mNumElemBytes = 4;
		}else{
			MYGUI_PLATFORM_EXCEPT("format not support");
		}
		mDataSize = _width * _height * mNumElemBytes;
		setUsage(_usage);
		mOriginalFormat = _format;
		mOriginalUsage = _usage;
        _mTexture=egg::Texture2DPtr(new egg::Texture2D(eggPF,_width,_height));
	}

	void EggTexture::destroy()
	{
		if (mRenderTarget != nullptr)
		{
			delete mRenderTarget;
			mRenderTarget = nullptr;
		}
		mLock = false;
		mDataSize = 0;
		mUsage = 0;
		mBuffer = 0;
		mAccess = 0;
		mNumElemBytes = 0;
		mOriginalFormat = PixelFormat::Unknow;
		mOriginalUsage = TextureUsage::Default;
	}

	void* EggTexture::lock(TextureUsage _access){
		if (_access == TextureUsage::Read){
			mBuffer = new unsigned char[mDataSize];
            _mTexture->readPixels(mBuffer);
            mLock = false;
			return mBuffer;
		}
		mBuffer = new unsigned char[mDataSize];
		mLock = true;
		return mBuffer;
	}

	void EggTexture::unlock(){
		if (!mLock && mBuffer){
			delete mBuffer;
			mBuffer = 0;
			return;
		}
        _mTexture->writePixels(mBuffer);
		delete mBuffer;
		mBuffer = 0;
		mLock = false;
	}

	void EggTexture::loadFromFile(const std::string& _filename){
        using namespace egg;
        Image2D img(DataManager::getInstance().getDataPath(_filename),0);
        _mTexture=Texture2DPtr(new Texture2D(img));
	}

	void EggTexture::saveToFile(const std::string& _filename){
	}

	IRenderTarget* EggTexture::getRenderTarget(){
		if (mRenderTarget == nullptr)
			mRenderTarget = new EggRTTexture(_mTexture);

		return mRenderTarget;
	}

	int EggTexture::getWidth(){
		return _mTexture->getWidth();
	}

	int EggTexture::getHeight(){
		return _mTexture->getHeight();
	}

	bool EggTexture::isLocked()
	{
		return mLock;
	}

	PixelFormat EggTexture::getFormat()
	{
		return mOriginalFormat;
	}

	TextureUsage EggTexture::getUsage()
	{
		return mOriginalUsage;
	}

	size_t EggTexture::getNumElemBytes()
	{
		return mNumElemBytes;
	}

} // namespace MyGUI
